# This file is part of OrangeSpider. OrangeSpider is a meta model based
# development tool.
# 
# OrangeSpider is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
# 
# OrangeSpider is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
# 
# You should have received a copy of the GNU General Public License
# along with OrangeSpider.  If not, see <http://www.gnu.org/licenses/>.
#
# Copyright 2009 Stefan Nikolaus <OrangeSpiderMaster@googlemail.com>

from MetaModel import *
import sys
from PyQt4.QtCore import *
from PyQt4.QtGui import *
import Component
from Types import *
import ComponentManager
from Project import *
import os.path
from Algorithms import *
import Ui
import Component

class Package(Project):
    def __init__(self):
        pass
    def autoLoad(self):
        self._autoLoad()
    def getPackageReferences(self):
        references = []
        package = self.getPackage()
        for requiredPackage in package.eachOutgoingClass("Package.Requires.Package"):
            references.append(requiredPackage["Name"])
        return references
    def getPackage(self):
        main = self.getMainFolder()
        package = main.firstIncomingClass("Package.Has.Folder")
        return package
    
class PackageManager(Component.Component):
    def __init__(self):
        Component.Component.__init__(self)
        self.packageFolders = set()
        self.addPackageFolder("Packages")
        self.packages = {}
        
        # This metamodel is the result of a merge of all installed packages
        # Maybe this will be stored later as "registred packages" metamodel
        # for fast startup
        r = buildMetaModel("PackageManager", "SpiderPROJECT", Watcher())
        self.repository = r
        self.repository.watcher.addListener(Ui.Emitter(), "Emitter")

    def interface(self, interfaceName):
        if interfaceName == "Spider.IManagedComponent":
            return self

        # Interface Spider.IManagedComponent
    @staticmethod
    def setupComponentType(rSpiderCOMP):
        return Component.Component._setupComponentType(rSpiderCOMP , "Spider.Package.PackageManager",
                                                       "Package management",
                                                       1, ["Spider.IManagedComponent"])


    def addPackageFolder(self, folderName):
        self.packageFolders.add(folderName)
        
    def install(self, package, packageFolder):
        pass
    
    def uninstall(self, package):
        # deletes a project from the packages folder (wholly)
        pass

    def loadPackage(self, packageName):
        importedPackages = []
        self._loadPackage(importedPackages, packageName)

        # 5. do the autoload of all packages
        for package in importedPackages:
            package.autoLoad()
            
    def _loadPackage(self, importedPackages, packageName):
        if packageName in self.packages:
            # already loaded
            return

        # 1. from package name build a possible path to the package file
        l = packageName.split(".")
        sep = ""
        filename = ""
        newPath = ""
        for n in l:
            newPath += sep + n
            sep = "/"
            filename = n + ".spid"
        newPath += sep + filename
        print newPath
        
        # 2. search package in all package folders
        packagePath = ""
        for pf in self.packageFolders:
            checkPath = pf + "/" + newPath
            if os.path.exists(checkPath):
                packagePath = checkPath
                break

        # 3. load package (as project).
        if packagePath == "":
            print "Package %s not found " % packageName

        print packagePath
        package = Package()
        package.load(packagePath, False)
        self.packages[packageName] = package

        self._importPackageData(package, packageName)
        
        # 4. resolve all package references
        requiredPackages = package.getPackageReferences()
        for requiredPackage in requiredPackages:
            self._loadPackage(importedPackages, requiredPackage)
        importedPackages.append(package)

    def _importPackageData(self, package, packageName):

        # copy the imported package data to the main package repository
        r = self.repository
        p = r.Class("Package")
        p["Name"] = packageName

        importedPackage = package.getPackage()
        assert(importedPackage)
        copyDict(importedPackage, p)

        for setting in importedPackage.eachOutgoingClass("Package.Has.Setting"):
            s = r.Class("Setting")
            copyDict(setting, s)
            r.Assoc(p, s, "Has")

        for requiredPackage in importedPackage.eachOutgoingClass("Package.Requires.Package"):
            name = requiredPackage["Name"]
            reqP = r.find("Package", "Name", name)
            r.assoc(p, reqP, "Requires")
            


if __name__ == "__main__":
    app = QApplication(sys.argv)
    # import org.spider.Documentation
    #pm = PackageManager()
    #pm.loadPackage("org.spider.Test1")
    #r = pm.repository
    #r.watcher.addListener(Ui.Emitter(), "Emitter")
    #mw = Ui.MatrixWidget(r)
    #mw.exec_()

    # Add our package folder to the import path
    sys.path.append("./Packages")
    import org.Spider.Test1
    
    
    

